package com.example.demo4;

import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;

public class MyArrayList<E> {
    private Object[] elementData = {};
    private int size; // 记录元素个数,记录下个位置
    private int DEFAULT_CAPACITY = 10; // 默认容量

    public boolean add(E e) {
        // 1.判断是否需要扩容
        if (size == elementData.length) {
            grow();
        }
        elementData[size++] = e;
        return true;
    }

    public int size() {
        return size;
    }

    // 使用官方的Consumer
    /*public void forEach(Consumer<E> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept((E) elementData[i]);
        }
    }*/

    // 自定义的函数式接口
    public void forEach(MyConsumer<E> action) {
        // 判断是否为空
        Objects.requireNonNull(action);
        for (int i = 0; i < size; i++) {
            action.accept((E) elementData[i]);
        }
    }

    public E remove(int index) {
        checkIndex(index);
        E e = (E) elementData[index];
        // 删除数据之前需要先判断是否要进行元素移位
        int moveFlag = size - index - 1; // 需要移动的个数的算法就是size - 要删除的索引 - 1
        if (moveFlag != 0) {
            // 说明要移位
            /**
             * 参数一：源数组
             * 参数二：从哪里开始拷贝 -> 从要删除索引的下一个位置
             * 参数三：目标数组 -> 拷贝到哪里去
             * 参数四：从源数组的第几个位置开始拷贝
             * 参数五：拷贝几个元素
             */
            System.arraycopy(elementData, index + 1, elementData, index, moveFlag);
        }
        // 把最后一个元素改成null
        elementData[--size] = null;
        return e;
    }

    public E get(int index) {
        // 判断索引是否越界
        checkIndex(index);
        // 根据索引获取元素
        return (E) elementData[index];
    }

    /**
     * 检查索引是否越界
     *
     * @param index 索引
     */
    public void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }
    }

    /**
     * 扩容算法
     */
    private void grow() {
        // 1.判断是否是第一次扩容
        if (size == 0) {
            // 说明是第一次扩容
            elementData = new Object[DEFAULT_CAPACITY];
        } else {
            // 说明不是第一次扩容,扩容成原来的1.5倍    >> 右移为原来大小的一半
            elementData = Arrays.copyOf(elementData, elementData.length + elementData.length >> 1);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            E e = (E) elementData[i];
            sb.append(e).append(i == size - 1 ? "" : ", ");
            // 尽量不要这样写
            // sb.append((i == size - 1 ? elementData[i] : elementData[i] + ", "));
        }
        sb.append("]");
        return sb.toString();
    }
}
